/************************************************************************************
 *   Cliente.																		*
 *   Programa cria um vetor aleaório, ordena e envia para o servidor de 1º nível    *
 *                                                                                  *
 *      Laís Pessine do Carmo           7546760                                     *
 *      Marcelo Pinheiro Montanher      7236527                                     *
 ************************************************************************************/

/************************************************************
 *      O modelo de uso de sockets foi retirado do site:    *
 *     http://wiki.netbsd.org/examples/socket_programming/  *
 ************************************************************/


#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <time.h>
#include <sys/time.h>

#define SIZE_ARRAY 125
#define MAX_VALUE 1000
#define MICRO_PER_SECOND 1000000


int start_connection(int *sock,int porta, char *ip){
    struct sockaddr_in echoserver;
    if((*sock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0){
        printf("Erro ao criar socket\n");
        return 1;
    }

    memset(&echoserver,0,sizeof(echoserver));
    echoserver.sin_family=AF_INET;
    echoserver.sin_addr.s_addr=inet_addr(ip);
    echoserver.sin_port=htons(porta);
    if(connect(*sock,(struct sockaddr *)&echoserver,sizeof(echoserver))<0){
        printf("Erro ao conectar ao servidor!\n");
        return 1;
    }

    return 0;
}

// Ordena vetor através do método Quick Sort (código fornecido gentilmente pela Wikipedia)
void quickSort(int valor[], int esquerda, int direita)
{
    int i, j, x, y;
    i = esquerda;
    j = direita;
    x = valor[(esquerda + direita) / 2];

    while(i <= j)
    {
        while(valor[i] < x && i < direita)
        {
            i++;
        }
        while(valor[j] > x && j > esquerda)
        {
            j--;
        }
        if(i <= j)
        {
            y = valor[i];
            valor[i] = valor[j];
            valor[j] = y;
            i++;
            j--;
        }
    }
    if(j > esquerda)
    {
        quickSort(valor, esquerda, j);
    }
    if(i < direita)
    {
        quickSort(valor,  i, direita);
    }
}

/** Inicia vetores aleatórios                                           *
  * size - Tamanho do Vetor                                             *
  * max_range - Valor Máximo que cada elemento do vetor pode receber    */
int *start_array(int size,int max_range){
    int *vet=(int*)malloc(sizeof(int)*size+1);
    for(int i=0;i<size;i++){
        vet[i]=rand()%max_range+1; // Gera numero aleatorio de 0 a 'max_range'
    }
    return vet;
}

// Imprime vetor na tela
void print_array(int *vet,int size){
    int i;
    for(i=0;i<size;i++){
        printf("%d ",vet[i]);
    }
    printf("\n");
}

int main(int argc, char *argv[]){

    int sock;
    char *ip=argv[1];
    int porta=atoi(argv[2]); // O programa recebe por parametro a porta que deve enviar o vetor
    int bytes;

    struct timeval start_time;
    struct timeval stop_time;
    float time_com,time_total;

    srand((unsigned)time(NULL));

    if(start_connection(&sock,porta,ip)==1){
        return 1;
    }
    printf("Cliente conectado!\n");

    int *vet=start_array(SIZE_ARRAY,MAX_VALUE); //Inicia Vetor
    int vet_final[SIZE_ARRAY*8];

    quickSort(vet,0,SIZE_ARRAY);

    gettimeofday( &start_time, NULL );  // Marca o tempo antes do envio do vetor

    send(sock,vet,sizeof(int)*SIZE_ARRAY,0);

    bytes=recv(sock,vet_final,sizeof(int)*SIZE_ARRAY*8,MSG_WAITALL); // Recebe vetor final
    if(bytes==-1){
        printf("Erro ao receber vetor final");
    }

    gettimeofday( &stop_time, NULL );

    time_com = (float)(stop_time.tv_sec - start_time.tv_sec);
    time_com += (stop_time.tv_usec - start_time.tv_usec)/(float)MICRO_PER_SECOND;

    // Imprimimos o vetor recebido
    printf("\nVetor recebido:\n");
    print_array(vet_final,SIZE_ARRAY*8);

    gettimeofday( &stop_time,NULL);

    time_total=(float)(stop_time.tv_sec - start_time.tv_sec);
    time_total+=(stop_time.tv_usec - start_time.tv_usec)/(float)MICRO_PER_SECOND;


    printf("\nTempo de comunicacaodo cliente: %f",time_com);
    printf("\nTempo total do cliente: %f",time_total);



    // Fecha socket
    close(sock);

    return 0;
}

